package com.yueke.gemini.utils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *中文日期转数字日期
 * 格式： [上下 午][XX]时[XX]分[XX]秒 转换成 XX:XX:XX
 *
 * 你好，偶然看到你的代码， 作为一个Code Reviewer， 给你几点小小建议：

 基本规范： 比如TAB键问题， java命名原则：驼峰， 比如“CheckedInputStr” “num_Time_Arr” 代码缩进整齐，格式化问题
 代码复杂度： 方法圈复杂度， if for等语句在一个方法中出现的次数和产生的层级，适可少。 命名易读性：尽可能见名知意。 比如一些不好的 “numS” “s”之类的
 测试规范： 使用单元测试，而不是main函数
 希望对你有帮助， 码代码要从基础抓起哦 :relaxed:
 */
public class TimeConvertUtil {

    /**
     * 用于分割时间
     */
    private static final String DIV_STR = ":";
    /**
     * 错误返回
     */
    private static final String ERROR_RETURN = "";
    /**
     * 用于分割时间
     */
    private static final String[] PREFIX = {"上","下","午"};

    /**
     * 12时制
     */
    public static final String FORMATTER_12H = "12H";
    /**
     * 24时制
     */
    public static final String FORMATTER_24H = "24H";
    /**
     * 零
     */
    public static final String ZERO = "0";
    /**
     * 十
     */
    public static final String TEN = "十";
    /**
     * 前缀，分割，数字
     */
    private static final char[] ALL_CN_CHAR = {
            '上','下','午',
            '时','点','分','秒','半','刻','整',
            '〇','零','一','二','三','四','五','六','七','八','九','十','两'};
    private static final String[] ALL_CN_NUM = {
            "0","12",":",
            ":",":",":","","30:00","15","00:00",
            "0","0","1","2","3","4","5","6","7","8","9","十", "2"};

    /**
     *
     * @param time 格式： [上/下 午][XX]时[XX]分[XX]秒
     * @return 12时制 时间
     */
    public static String timeConvert(String time) {
        return timeConvert(time, FORMATTER_12H);
    }


    /**
     *
     * @param time 格式： [上/下 午][XX]时[XX]分[XX]秒
     * @param formatter 12时制/24时制
     * @return 12时制/24时制 时间
     */
    public static String timeConvert(String time, String formatter) {

        if(!(formatter.equals(FORMATTER_12H) || formatter.equals(FORMATTER_24H))) {
            System.err.println("parameter formatter is unexpected. [" + formatter + "]" + time);
            return ERROR_RETURN;
        }
        // 十，分，秒  对应的数字
        int[] numTime = {0,0,0};
        char[] timeArr = time.toCharArray();
        try {
            CheckedInputStr(timeArr);
        } catch (Exception e) {
            System.err.println(e.getMessage() + " " + time);
            return ERROR_RETURN;
        }

        // 是否有前缀
        boolean prefix = hasPerfix(time);

        StringBuffer buf = new StringBuffer();
        for (char tc:timeArr) {
            for(int i = 0; i < ALL_CN_CHAR.length; i++) {
                if(tc == ALL_CN_CHAR[i]) {
                    buf.append(ALL_CN_NUM[i]);
                }
            }
        }

        String[] num_Time_Arr = buf.toString().split(DIV_STR);

        // 对十进行处理
        for(int i = 0; i < num_Time_Arr.length;i++) {
            if(num_Time_Arr[i].equals("")) {
                num_Time_Arr[i] = "0";
                continue;
            }
            num_Time_Arr[i] = handleTen(num_Time_Arr[i]);
        }

        // 前缀需要加的时间
        int perNum = 0;

        int idx = 0;

        if(prefix) {
            perNum = Integer.parseInt(num_Time_Arr[idx++]);
        }

        for(int i = idx; i < num_Time_Arr.length && i < (numTime.length + idx); i++) {
            numTime[i - idx] = Integer.parseInt(num_Time_Arr[i]);
        }

        numTime[0] += perNum;

        if(formatter.equals(FORMATTER_24H)) {
            numTime[0] = numTime[0] % 100 % 24;
        } else if(formatter.equals(FORMATTER_12H)) {
            numTime[0] = numTime[0] % 100 % 12;
        }
        numTime[1] = numTime[1] % 100 % 60;
        numTime[2] = numTime[2] % 100 % 60;

        StringBuffer final_buf = new StringBuffer();
        final_buf.append(numTime[0] < 10? ZERO + numTime[0]: numTime[0]);
        final_buf.append(DIV_STR);
        final_buf.append(numTime[1] < 10? ZERO + numTime[1]: numTime[1]);
        final_buf.append(DIV_STR);
        final_buf.append(numTime[2] < 10? ZERO + numTime[2]: numTime[2]);

        return final_buf.toString();
    }

    /**
     * 分情况给"十"赋值
     * @param string
     * @return
     */
    private static String handleTen(String numS) {
        int idx = numS.indexOf(TEN);

        if(idx >= 0) {
            int len = numS.length();
            // 替换中文
            String reg = "[\u4e00-\u9fa5]";

            Pattern pat = Pattern.compile(reg);

            Matcher mat=pat.matcher(numS);

            if(len == 1) { // 只有一个十
                numS = mat.replaceAll("10");
            } else if(idx == 0) { // 在开头
                numS = mat.replaceAll("1");
            } else if (idx == numS.length() - 1) { // 在结尾
                numS = mat.replaceAll("0");
            } else {
                numS = mat.replaceAll("");
            }
        }
        return numS;
    }


    /**
     * 是否有前缀 "上","下","午"
     * @param time
     * @return
     */
    private static boolean hasPerfix(String time) {
        for(String per:PREFIX) {
            if(time.indexOf(per) >= 0)
                return true;
        }
        return false;
    }

    /**
     * 检测输入有无期望以外的值
     * @param time
     * @throws Exception
     */
    private static void CheckedInputStr(char[] time) throws Exception {
        if(time.length <= 0)
            throw new Exception("length of time string unexpected " + time.length + ".");
        boolean in_Arr = false;
        char ch_temp = ' ';
        for(char s:time) {
            ch_temp = s;
            in_Arr = false;
            for(char cns:ALL_CN_CHAR) {
                if(s==cns) {
                    in_Arr = true;
                    break;
                }
            }

            if(!in_Arr)
                throw new Exception("unexpected character [" + ch_temp + "] in time string. [" + ch_temp + "] ");
        }
    }

    public static void main(String[] args) {
        // 正例
        System.out.println(timeConvert("二十三时十五分十五秒"));
        System.out.println(timeConvert("十三点一刻"));
        System.out.println(timeConvert("上午十点零五分五秒"));
        System.out.println(timeConvert("下午三时五十分五十秒"));
        System.out.println(timeConvert("十三时整"));
        System.out.println(timeConvert("十三时半"));
        System.out.println(timeConvert("十时十分十秒"));
        System.out.println(timeConvert("二十六时十分十秒"));
        System.out.println(timeConvert("二十四时十分十秒"));

        System.out.println(timeConvert("二十三时十五分十五秒", FORMATTER_24H));
        System.out.println(timeConvert("十三点一刻", FORMATTER_24H));
        System.out.println(timeConvert("上午十点零五分五秒", FORMATTER_24H));
        System.out.println(timeConvert("下午三时五十分五十秒", FORMATTER_24H));
        System.out.println(timeConvert("十三时整", FORMATTER_24H));
        System.out.println(timeConvert("十三时半", FORMATTER_24H));
        System.out.println(timeConvert("十时十分十秒", FORMATTER_24H));
        System.out.println(timeConvert("下午十时十分十秒", FORMATTER_24H));
        System.out.println(timeConvert("二十六时十分十秒", FORMATTER_24H));
        System.out.println(timeConvert("二十四时十分十秒", FORMATTER_24H));

        // 反例
        System.out.println(timeConvert("下午十午时十下分十整秒"));
        System.out.println(timeConvert("下午三十十时十分十秒1"));
        System.out.println(timeConvert("上午三十十时十分十秒"));
        System.out.println(timeConvert("下午十三十时十分十秒"));
        System.out.println(timeConvert("下午十三十时十分十秒"));
        System.out.println(timeConvert("下午十时十分十秒", "12"));
        System.out.println(timeConvert("下午十整时十分十秒"));
        System.out.println(timeConvert("下午十时整十分十秒"));
        System.out.println(timeConvert("下午十时整十分整十秒"));
        System.out.println(timeConvert("下午十时十分十秒整"));
        System.out.println(timeConvert("下午十半时十分十秒"));
        System.out.println(timeConvert("下午十时半十分十秒"));
        System.out.println(timeConvert("下午十时十分半十秒"));
        System.out.println(timeConvert("下午十时十分十秒半"));

        System.out.println(timeConvert("下午十午时十下分十整秒", FORMATTER_24H));
        System.out.println(timeConvert("下午三十十时十分十秒1", FORMATTER_24H));
        System.out.println(timeConvert("上午三十十时十分十秒", FORMATTER_24H));
        System.out.println(timeConvert("下午十三十时十分十秒", FORMATTER_24H));
        System.out.println(timeConvert("下午三十时十分十秒", FORMATTER_24H));
        System.out.println(timeConvert("下午十时十分十秒", "12"));
        System.out.println(timeConvert("下午十时十分十秒", FORMATTER_24H));
        System.out.println(timeConvert("下午十时十分十秒", FORMATTER_24H));
    }
}
